﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Configuration;
using System.Xml;

namespace KPIS
{ 
    public static partial class GerpResources
    {
        #region Public Member

        // Current Resource File Using (.resx) - Share to whole server users (Static)
        public static string XmlFullPath;

        // Current Resource Object XML - Share to whole server users (Static)
        public static XmlDocument X; 

        /// <summary>
        /// Method to get Resource By Custom ResourceFileName, such as HA.resx
        /// There must config to web.config as key "DeploySite", value "{filename}"
        /// If not config resx file name, then it's use "Default" as filename
        /// 
        /// If key exist, it'll read from resx
        /// If key not exist, it'll create new key to that resx file, and value = key as initial
        /// 
        /// This type of resx to use is GlobalResources
        /// 
        /// How to use: just call KPIS.GerpResources.Get("Key of resource")
        /// </summary>
        /// <param name="key">key of resource, you want to get.</param>
        /// <returns>value of resource you got</returns>
        public static string Get(string key)
        {
            if (_temp.ContainsKey(key))
            {
                return _temp[key];
            }

            Check();
            string value = Read(key);
            _temp.Add(key, value);
            return value;
        }
        #endregion

        #region Private Member

        private static Dictionary<string, string> _temp;

        private static void Check()
        {
            CheckResourceFilePath();
            CheckResourceXml();
        }

        private static string Read(string key)
        {
            string result = String.Empty;
            XmlNode nodeValue = ReadNodeAndCreateIfNotExist(key);
            if (nodeValue != null)
            {
                result = nodeValue.InnerText;
            }
            return result;
        }

        private static XmlNode ReadNodeAndCreateIfNotExist(string key)
        {
            string dataPath = String.Format("root/data[@name='{0}']/value", key);
            if (!String.IsNullOrEmpty(XmlFullPath) && X != null)
            {
                const string rootPath = "root";
                var nodeRoot = X.SelectSingleNode(rootPath);
                var nodeValue = X.SelectSingleNode(dataPath);

                if (nodeRoot != null && nodeValue == null)
                {
                    var nodeData = X.CreateNode(XmlNodeType.Element, "data", null);
                    nodeValue = X.CreateNode(XmlNodeType.Element, "value", null);

                    {
                        XmlAttribute nodeAttributeName = X.CreateAttribute("name");
                        nodeAttributeName.Value = key;
                        if (nodeData.Attributes != null)
                        {
                            nodeData.Attributes.Append(nodeAttributeName);
                        }
                        nodeValue.InnerText = key;
                        nodeData.AppendChild(nodeValue);
                        nodeRoot.AppendChild(nodeData);
                    }

                    using (var writer = new XmlTextWriter(XmlFullPath, System.Text.Encoding.UTF8))
                    {
                        writer.Formatting = Formatting.Indented;
                        X.Save(writer);
                        writer.Close();
                    } 

                }

            }

            return X != null ? X.SelectSingleNode(dataPath) : null;
        }

        private static void CheckResourceXml()
        {
            if (!String.IsNullOrEmpty(XmlFullPath) && X == null && System.IO.File.Exists(XmlFullPath))
            {
                // Normal Read
                try
                {
                    var xmlDocumentTemp = new XmlDocument();
                    var reader = new XmlTextReader(XmlFullPath) {WhitespaceHandling = WhitespaceHandling.None};
                    xmlDocumentTemp.Load(reader);
                    reader.Close();
                    X = xmlDocumentTemp;
                }
                catch (Exception ex)
                {
                    // Error On Read Above, Create New Xml
                    CreateEmptyResx();
                }
            } else if (!String.IsNullOrEmpty(XmlFullPath) && X == null && !System.IO.File.Exists(XmlFullPath))
            {
                CreateEmptyResx();
            }
        }

        private static void CreateEmptyResx()
        {
            if (System.IO.File.Exists(XmlFullPath))
                System.IO.File.Delete(XmlFullPath);

            {
                System.IO.File.WriteAllLines(XmlFullPath, new[] { EmptyResx });
            }

            try
            {
                var xmlDocumentTemp = new XmlDocument();
                var reader = new XmlTextReader(XmlFullPath) {WhitespaceHandling = WhitespaceHandling.None};
                xmlDocumentTemp.Load(reader);
                reader.Close();
                X = xmlDocumentTemp;
            }
            catch (Exception ex)
            {
                
            }
        }

        private static void CheckResourceFilePath()
        {
            if (String.IsNullOrEmpty(XmlFullPath))
            {
                string deploySite;
                try
                {
                    string valueDeploySite = WebConfigurationManager.AppSettings["DeploySite"];
                    if (!String.IsNullOrEmpty(valueDeploySite))
                        deploySite = valueDeploySite + ".resx";
                    else
                        deploySite = "Default.resx";
                }
                catch (Exception ex)
                {
                    deploySite = "Default.resx";
                }

                if (deploySite.Contains("/") || deploySite.Contains(@"\"))
                {
                    XmlFullPath = HttpContext.Current.Server.MapPath(deploySite);
                }
                else
                {
                    XmlFullPath = HttpContext.Current.Server.MapPath("/App_GlobalResources/" + deploySite);
                }
            }
        }
        #endregion
    }

    public static partial class GerpResources
    {
        #region Public Member2
        public static string EmptyResx = 
@"<?xml version='1.0' encoding='utf-8'?>
<root>
  <xsd:schema id='root' xmlns='' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:msdata='urn:schemas-microsoft-com:xml-msdata'>
    <xsd:import namespace='http://www.w3.org/XML/1998/namespace' />
    <xsd:element name='root' msdata:IsDataSet='true'>
      <xsd:complexType>
        <xsd:choice maxOccurs='unbounded'>
          <xsd:element name='metadata'>
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name='value' type='xsd:string' minOccurs='0' />
              </xsd:sequence>
              <xsd:attribute name='name' use='required' type='xsd:string' />
              <xsd:attribute name='type' type='xsd:string' />
              <xsd:attribute name='mimetype' type='xsd:string' />
              <xsd:attribute ref='xml:space' />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name='assembly'>
            <xsd:complexType>
              <xsd:attribute name='alias' type='xsd:string' />
              <xsd:attribute name='name' type='xsd:string' />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name='data'>
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name='value' type='xsd:string' minOccurs='0' msdata:Ordinal='1' />
                <xsd:element name='comment' type='xsd:string' minOccurs='0' msdata:Ordinal='2' />
              </xsd:sequence>
              <xsd:attribute name='name' type='xsd:string' use='required' msdata:Ordinal='1' />
              <xsd:attribute name='type' type='xsd:string' msdata:Ordinal='3' />
              <xsd:attribute name='mimetype' type='xsd:string' msdata:Ordinal='4' />
              <xsd:attribute ref='xml:space' />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name='resheader'>
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name='value' type='xsd:string' minOccurs='0' msdata:Ordinal='1' />
              </xsd:sequence>
              <xsd:attribute name='name' type='xsd:string' use='required' />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name='resmimetype'>
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name='version'>
    <value>2.0</value>
  </resheader>
  <resheader name='reader'>
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name='writer'>
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
</root>";
        #endregion
    }
}